#pragma once

#include<iostream>
using namespace std;
#include<string>
#include<functional>
#include<pthread.h>
#include<cassert>


class Thread;

//上下文：用来去调用新线程执行流的函数
class Context{
public:
    Context():_this(nullptr),_args(nullptr){

    }
    ~Context(){

    }
public:
    Thread* _this;
    void* _args;
};








class Thread{
public:
    typedef function<void*(void*)> func_t;//这里封装的就是新线程的执行流

    //构造函数：封装的是pthread_create()
    //要传入的参数有新线程的执行流，执行流的参数，编号
    Thread(func_t func,void* args = nullptr,int number = 0):_func(func),_args(args){
        char buffer[1024];
        snprintf(buffer,sizeof buffer,"thread:%d",number);
        _name = buffer;

        Context* ctx = new Context();
        ctx->_this = this;
        ctx->_args = _args;
        int n = pthread_create(&_tid,nullptr,start_routine,ctx);
        assert(n == 0);
        (void)n;
    }

    //在类创建线程，想让线程执行对应的方法，需要将方法设置为静态，这样就没有this指针了
    static void* start_routine(void* args){//类内成员函数，有一个隐藏的this指针，所以创建线程只能传一个参数是不对的
    //所以这里使用一个类来接受2个传参，一个this，一个args
        //return _func(_args);
        Context* ctx = static_cast<Context*>(args);//ctx结构体
        void* ret = ctx->_this->run(ctx->_args);
        delete ctx;
        //静态方法不能调用成员方法或者成员变量
        return ret;
    }

    void join(){
        int n = pthread_join(_tid,nullptr);
        assert(n == 0);
        (void)n;
    }

    void* run(void* args){
        return _func(args);
    }

    ~Thread(){
        //do nothing
    }

private:
    string _name;//创建出来的线程名称
    pthread_t _tid;//构造的tid，也就是新线程的tid
    func_t _func;//新线程的执行流
    void* _args;
};